<template>
  <div id="three">
    <el-card class="box-card">
      <el-button
        v-for="(item, index) in btns"
        :key="index"
        class="btn"
        :style="item == 'three' ? 'display:none' : ''"
        @click="btn(item)"
        >{{ item }}</el-button
      >
    </el-card>
  </div>
</template>

<script>
import { mapState } from "vuex";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { mergeBufferGeometries } from "three/examples/jsm/utils/BufferGeometryUtils";
import cat from "@/../public/static/cat.json";
const elementResizeDetector = require("element-resize-detector");

export default {
  computed: {
    ...mapState({
      btns: (state) => state.vuex.btns,
    }),
  },
  mounted() {
    this.init();
  },
  data() {
    return {
      num: 0,
      vector: null,
    };
  },
  methods: {
    init() {
      // 创建场景
      const scene = new THREE.Scene();
      // 网格模型
      const geometryArray = [];
      const materialArray = [];
      const data = cat;
      const ipx = data.length; // 144
      const jpx = data[0].length; // 192
      const l = 10; // 正方体边长
      for (let i = 0; i < ipx; i++) {
        for (let j = 0; j < jpx; j++) {
          const geometry = new THREE.BoxGeometry(l, l, l);
          const color = `rgb(${data[i][j].toString()})`;
          const material = new THREE.MeshLambertMaterial({
            color,
          });
          const mesh = new THREE.Mesh(geometry, material);
          mesh.position.set(j * l + l / 2, (ipx - i) * l - l / 2, l / 2);
          mesh.updateMatrix();
          const newGeometry = mesh.geometry.applyMatrix4(mesh.matrix);

          geometryArray.push(newGeometry);
          materialArray.push(material);
        }
      }
      const mergedGeometries = mergeBufferGeometries(geometryArray, true);
      const singleMergeMesh = new THREE.Mesh(mergedGeometries, materialArray);
      scene.add(singleMergeMesh);
      // 光
      // 环境光
      const ambient = new THREE.AmbientLight("#fff", 1);
      scene.add(ambient);
      // 相机
      let width = document.getElementById("three").clientWidth;
      let height = document.getElementById("three").clientHeight;
      const camera = new THREE.PerspectiveCamera(
        45,
        width / height,
        0.1,
        1000000
      );
      // 相机位置
      camera.position.set((jpx * l) / 2, (ipx * l) / 2, 2000);
      // 目标位置
      this.vector = {
        x: (jpx * l) / 2,
        y: (ipx * l) / 2,
        z: 0,
      };
      camera.lookAt(
        new THREE.Vector3(this.vector.x, this.vector.y, this.vector.z)
      );
      // 渲染器
      const renderer = new THREE.WebGLRenderer();
      renderer.setSize(width, height);
      // 渲染
      renderer.render(scene, camera);
      document.getElementById("three").appendChild(renderer.domElement);
      // 轨道控制器
      const controls = new OrbitControls(camera, renderer.domElement);
      controls.target.set((jpx * l) / 2, (ipx * l) / 2, 0);
      controls.addEventListener("change", () => {
        this.vector = JSON.parse(JSON.stringify(controls.target))
        renderer.render(scene, camera);
      });
      // 监听变化
      const erd = elementResizeDetector();
      erd.listenTo(document.getElementById("three"), () => {
        width = document.getElementById("three").clientWidth;
        height = document.getElementById("three").clientHeight;
        camera.aspect = width / height;
        camera.lookAt(new THREE.Vector3(this.vector.x, this.vector.y, this.vector.z))
        camera.updateProjectionMatrix();
        renderer.setSize(width, height);
        renderer.render(scene, camera);
      });
    },

    btn(val) {
      this.$router.push(`/${val}`);
    },
  },
};
</script>

<style lang="scss" scoped>
#three {
  width: 100%;
  height: 100%;
  overflow: hidden;

  .box-card {
    position: absolute;
    right: 10px;
    bottom: 10px;
    width: 140px;
    height: 440px;
    background-color: rgba($color: #000000, $alpha: 0.6);
    z-index: 1000;
    :deep(.el-card__body) {
      text-align: center;
    }
    .btn {
      width: 100px;
      margin: 0 0 5px;
      background-color: transparent;
      color: #fff;
      &:hover {
        background-color: rgba($color: #000, $alpha: 0.6);
      }
    }
  }
}
</style>
